#include "SaveJson.h"
#include <iostream>
#include "kernel/cjson/cJSON.h"
#include "base/Intent.h"
#include <log/log_err.h>
#include <kernel/sign_kernel.h>

static const char *INTER = "inter";
static const char *DOUBLE = "double";
static const char *STRING = "string";
static const char *BOOLEAN = "boolen";

SaveJson::SaveJson(/* args */)
{
}

SaveJson::~SaveJson()
{
}

/* 将Intent保存在filename中 true:1 false:0 */
bool SaveJson::saveIntent(const char* filename, const Intent& intent)
{
    cJSON *root = nullptr;
    cJSON *arrayInter = nullptr;
    cJSON *arrayDouble = nullptr;
    cJSON *arrayString = nullptr;
    cJSON *arrayBool = nullptr;
    cJSON *item = nullptr;
    std::string buffer;

    root = cJSON_CreateObject();
    arrayInter = cJSON_CreateArray();
    arrayDouble = cJSON_CreateArray();
    arrayString = cJSON_CreateArray();
    arrayBool = cJSON_CreateArray();

    for(auto &it : intent.m_extra_i){
        item = cJSON_CreateObject();
        cJSON_AddNumberToObject(item, it.first.c_str(), it.second);
        cJSON_AddItemToArray(arrayInter, item);
    }

    for(auto &it : intent.m_extra_d){
        item = cJSON_CreateObject();
        cJSON_AddNumberToObject(item, it.first.c_str(), it.second);
        cJSON_AddItemToArray(arrayDouble, item);
    }

    for(auto &it : intent.m_extra_s){
        item = cJSON_CreateObject();
        cJSON_AddStringToObject(item, it.first.c_str(), it.second.c_str());
        cJSON_AddItemToArray(arrayString, item);
    }
    
    for(auto &it : intent.m_extra_b){
        item = cJSON_CreateObject();
        if (it.second) {
            cJSON_AddTrueToObject(item, it.first.c_str());
        } else {
            cJSON_AddFalseToObject(item, it.first.c_str());
        }
        cJSON_AddItemToArray(arrayBool, item);
    }

    cJSON_AddItemToObject(root, INTER, arrayInter);
    cJSON_AddItemToObject(root, DOUBLE, arrayDouble);
    cJSON_AddItemToObject(root, STRING, arrayString);
    cJSON_AddItemToObject(root, BOOLEAN, arrayBool);

    buffer = (cJSON_Print(root) == NULL) ? "" : cJSON_Print(root);
    SIGNWAY_LOGI("\n%s", buffer.c_str());

    updateFile(filename, buffer);

RETURN:
    if (root != nullptr) {
        cJSON_Delete(root);
    }
}

/* filename文件内容转Intent */
bool SaveJson::loadIntent(const char* filename, Intent& intent)
{
    size_t i = 0;
    cJSON *root = nullptr;
    cJSON *arrayInter = nullptr;
    cJSON *arrayDouble = nullptr;
    cJSON *arrayString = nullptr;
    cJSON *arrayBool = nullptr;
    cJSON *item = nullptr;
    cJSON *obj = nullptr;
    std::string buffer;

    getFileInfo(filename, buffer);
    SIGNWAY_LOGI("\n%s", buffer.c_str());

    root = cJSON_Parse(buffer.c_str());
    SIGNWAY_ERROR_GOTO(root == nullptr, RETURN, "root is null");

    arrayInter = cJSON_GetObjectItem(root, INTER);
    SIGNWAY_ERROR_GOTO(arrayInter == nullptr, RETURN, "arrayInter is null");

    arrayDouble = cJSON_GetObjectItem(root, DOUBLE);
    SIGNWAY_ERROR_GOTO(arrayDouble == nullptr, RETURN, "arrayDouble is null");

    arrayString = cJSON_GetObjectItem(root, STRING);
    SIGNWAY_ERROR_GOTO(arrayString == nullptr, RETURN, "arrayString is null");

    arrayBool = cJSON_GetObjectItem(root, BOOLEAN);
    SIGNWAY_ERROR_GOTO(arrayBool == nullptr, RETURN, "arrayBool is null");
 
    if (cJSON_IsArray(arrayInter)) {
        for (i = 0; i < cJSON_GetArraySize(arrayInter); i++)
        {
            item = cJSON_GetArrayItem(arrayInter, i);
            SIGNWAY_ERROR_CONTINUE((item == NULL) || (item->child == NULL), "[%d]item is NULL", i);

            obj = cJSON_GetObjectItem(item, item->child->string);
            SIGNWAY_ERROR_CONTINUE(obj == NULL, "[%d]obj is NULL", i);

            if (cJSON_IsNumber(obj)) {
                intent.putExtra(obj->string, (int)cJSON_GetNumberValue(obj));
                SIGNWAY_LOGI("%s:%d", obj->string, (int)cJSON_GetNumberValue(obj));
            }
        }
    }

    if (cJSON_IsArray(arrayDouble)) {
        for (i = 0; i < cJSON_GetArraySize(arrayDouble); i++)
        {
            item = cJSON_GetArrayItem(arrayDouble, i);
            SIGNWAY_ERROR_CONTINUE((item == NULL) || (item->child == NULL), "[%d]item is NULL", i);

            obj = cJSON_GetObjectItem(item, item->child->string);
            SIGNWAY_ERROR_CONTINUE(obj == NULL, "[%d]obj is NULL", i);

            if (cJSON_IsNumber(obj)) {
                intent.putExtra(obj->string, cJSON_GetNumberValue(obj));
                SIGNWAY_LOGI("%s:%.2f", obj->string, cJSON_GetNumberValue(obj));
            }
        }
    }

    if (cJSON_IsArray(arrayString)) {
        for (i = 0; i < cJSON_GetArraySize(arrayString); i++)
        {
            item = cJSON_GetArrayItem(arrayString, i);
            SIGNWAY_ERROR_CONTINUE((item == NULL) || (item->child == NULL), "[%d]item is NULL", i);

            obj = cJSON_GetObjectItem(item, item->child->string);
            SIGNWAY_ERROR_CONTINUE(obj == NULL, "[%d]obj is NULL", i);

            if (cJSON_IsString(obj)) {
                intent.putExtra(obj->string, std::string(cJSON_GetStringValue(obj)));
                SIGNWAY_LOGI("%s:%s", obj->string, cJSON_GetStringValue(obj));
            }
        }
    }

    if (cJSON_IsArray(arrayBool)) {
        for (i = 0; i < cJSON_GetArraySize(arrayBool); i++)
        {
            item = cJSON_GetArrayItem(arrayBool, i);
            SIGNWAY_ERROR_CONTINUE((item == NULL) || (item->child == NULL), "[%d]item is NULL", i);

            obj = cJSON_GetObjectItem(item, item->child->string);
            SIGNWAY_ERROR_CONTINUE(obj == NULL, "[%d]obj is NULL", i);

            if (cJSON_IsBool(obj)) {
                bool value = false;
                if (cJSON_IsTrue(obj)) {
                    value = true;
                }
                intent.putExtra(obj->string, value);
                SIGNWAY_LOGI("%s:%s", obj->string, value ? "true":"false");
            }
        }
    }

RETURN:
    if (root != nullptr) {
        cJSON_Delete(root);
    }
}
